﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DXBase.D3D
{
	public class ConstantBuffer<T> : IList<T>
		where T : struct
	{
		DXBase.D3D.Buffer buffer;
		Pointer<T> data;

		public ConstantBuffer(Pointer<T> data)
		{
			if (data == null)
				throw new ArgumentNullException();
			this.data = data;

			buffer = new DXBase.D3D.Buffer
			{
				InitData = new DXBase.D3D.SubresourceData { Mem = data.Native },
				BindFlags = DXBase.D3D.BindFlag.ConstantBuffer,
			};
		}
		static ConstantBuffer()
		{
			if ((Pointer<T>.SizeOfType % 16) != 0)
				throw new ArgumentOutOfRangeException("sizeof(T) should be a multiple of 16");
		}

		public int Count
		{
			get { return data.Count; }
			set
			{
				if (value < 0 || value > (4094 * 4 * 16 / Pointer<T>.SizeOfType))
					throw new ArgumentOutOfRangeException();
				data.Count = value; 
			}
		}
		public T this[int index]
		{
			get { return data[index]; }
			set
			{
				data[index] = value;
				buffer.UpdateBuffer();
			}
		}

		public DXBase.D3D.Buffer Buffer { get { return Count > 0 ? buffer : null; } }
		public Pointer<T> Pointer { get { return data; } }

		// make it easy for object initializer
		public void Add(T item)
		{
			int i = Count;
			Count++;
			this[i] = item;
		}
		bool ICollection<T>.Contains(T item) { return data.Contains(item); }
		void ICollection<T>.CopyTo(T[] array, int arrayIndex) { data.CopyTo(array, arrayIndex); }
		bool ICollection<T>.IsReadOnly { get { return false; } }
		IEnumerator<T> IEnumerable<T>.GetEnumerator() { return data.GetEnumerator(); }
		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return data.GetEnumerator(); }
		int IList<T>.IndexOf(T item) { return data.IndexOf(item); }

		void ICollection<T>.Clear() { throw new NotSupportedException(); }
		bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); }
		void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); }
		void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); }

	}
}
